home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / mach / ds5000.md / machCode.c < prev    next >
C/C++ Source or Header  |  1991-08-09  |  67KB  |  2,397 lines

  1. /* 
  2.  * machCode.c --
  3.  *
  4.  *         C code for the mach module.
  5.  *
  6.  *    Copyright (C) 1989 Digital Equipment Corporation.
  7.  *    Permission to use, copy, modify, and distribute this software and
  8.  *    its documentation for any purpose and without fee is hereby granted,
  9.  *    provided that the above copyright notice appears in all copies.  
  10.  *    Digital Equipment Corporation makes no representations about the
  11.  *    suitability of this software for any purpose.  It is provided "as is"
  12.  *    without express or implied warranty.
  13.  */
  14.  
  15. #ifndef lint
  16. static char rcsid[] = "$Header: /sprite/src/kernel/mach/ds5000.md/RCS/machCode.c,v 1.6 91/08/02 17:41:20 jhh Exp $ SPRITE (DECWRL)";
  17. #endif not lint
  18.  
  19. #include <sprite.h>
  20. #include <stddef.h>
  21. #include <assert.h>
  22.  
  23. #include <machConst.h>
  24. #include <machMon.h>
  25. #include <machInt.h>
  26. #include <mach.h>
  27. #include <sys.h>
  28. #include <sync.h>
  29. #include <dbg.h>
  30. #include <proc.h>
  31. #include <procMigrate.h>
  32. #include <procUnixStubs.h>
  33. #include <sched.h>
  34. #include <vm.h>
  35. #include <vmMach.h>
  36. #include <sig.h>
  37. #include <sigMach.h>
  38. #include <swapBuffer.h>
  39. #include <net.h>
  40. #include <ultrixSignal.h>
  41.  
  42. /*
  43.  * Flag to set for new Unix compatiblity code.  Once the new
  44.  * code is working well enough, this flag should  be eliminated
  45.  * and the old compatibility code in machAsm.s, machUNIXSyscall.c etc.
  46.  * can be deleted.
  47.  */
  48.  
  49. int machNewUnixCompat;
  50.  
  51. /*
  52.  * Conversion of function to an unsigned value.
  53.  */
  54. #define F_TO_A    (Address)(unsigned)(int (*)())
  55. /*
  56.  *  Number of processors in the system.
  57.  */
  58. #ifndef NUM_PROCESSORS
  59. #define NUM_PROCESSORS 1
  60. #endif
  61.  
  62. int mach_NumProcessors = NUM_PROCESSORS;
  63.  
  64. /*
  65.  * TRUE if cpu was in kernel mode before the interrupt, FALSE if was in 
  66.  * user mode.
  67.  */
  68. Boolean    mach_KernelMode;
  69.  
  70. /*
  71.  *  Flag used by routines to determine if they are running at
  72.  *  interrupt level.
  73.  */
  74. Boolean mach_AtInterruptLevel = FALSE;
  75.  
  76. /*
  77.  * The machine type string is imported by the file system and
  78.  * used when expanding $MACHINE in file names.
  79.  */
  80.  
  81. char *mach_MachineType = "ds5000";
  82.  
  83. extern int debugProcStubs;
  84.  
  85. /*
  86.  * The byte ordering/alignment type used with Fmt_Convert and I/O control data
  87.  */
  88. Fmt_Format mach_Format = FMT_MIPS_FORMAT;
  89.  
  90. /*
  91.  *  Count of number of ``calls'' to enable interrupts minus number of calls
  92.  *  to disable interrupts.  Kept on a per-processor basis.
  93.  */
  94. int mach_NumDisableInterrupts[NUM_PROCESSORS];
  95. int *mach_NumDisableIntrsPtr = mach_NumDisableInterrupts;
  96.  
  97. /*
  98.  * The format that the kernel stack has to be in to start a process off.
  99.  */
  100. typedef struct {
  101.     int        magicNumber;        /* Magic number used to determine if
  102.                      * the stack has been corrupted. */
  103.     int        statusReg;        /* The status register value. */
  104.     int        filler[10];        /* Extra space on the stack to
  105.                      * store args and such. */
  106. } KernelStack;
  107.  
  108. /*
  109.  * The format of a signal stack that is pushed onto a user's stack when
  110.  * a signal is handled.
  111.  */
  112. typedef struct {
  113.     Sig_Stack    sigStack;
  114.     Sig_Context    sigContext;
  115. } SignalStack;
  116.  
  117. /*
  118.  * Machine dependent variables.
  119.  */
  120. Address    mach_KernStart;
  121. Address    mach_CodeStart;
  122. Address    mach_StackBottom;
  123. int    mach_KernStackSize;
  124. Address    mach_KernEnd;
  125. Address    mach_FirstUserAddr;
  126. Address    mach_LastUserAddr;
  127. Address    mach_MaxUserStackAddr;
  128. int    mach_LastUserStackPage;
  129.  
  130. char    mach_BitmapAddr[16];
  131. char    mach_BitmapLen[8];
  132.  
  133. /*
  134.  * The variables and tables below are used to dispatch kernel calls.
  135.  */
  136.  
  137. #define MAXCALLS 120
  138. #define MAXARGS  10
  139.  
  140. int machMaxSysCall;            /* Highest defined system call. */
  141. /*
  142.  * Tables to determine where to go to fetch the arguments for a system call.
  143.  */
  144. ReturnStatus (*machArgDispatch[MAXCALLS])();
  145. ReturnStatus (*machArgDispatchTable[])() = {
  146.     MachFetch0Args,
  147.     MachFetch0Args,
  148.     MachFetch0Args,
  149.     MachFetch0Args,
  150.     MachFetch0Args,
  151.     MachFetch1Arg,
  152.     MachFetch2Args,
  153.     MachFetch3Args,
  154.     MachFetch4Args,
  155.     MachFetch5Args,
  156.     MachFetch6Args,
  157. };
  158.  
  159. ReturnStatus (*(mach_NormalHandlers[MAXCALLS]))();
  160.                     /* For each system call, gives the
  161.                      * address of the routine to handle
  162.                      * the call for non-migrated processes.
  163.                      */
  164. ReturnStatus (*(mach_MigratedHandlers[MAXCALLS]))();
  165.                     /* For each system call, gives the
  166.                      * address of the routine to handle
  167.                      * the call for migrated processes. */
  168. int machKcallTableOffset;        /* Byte offset of the kcallTable field
  169.                      * in a Proc_ControlBlock. */
  170. int machStatePtrOffset;            /* Byte offset of the machStatePtr
  171.                      * field in a Proc_ControlBlock. */
  172. int machSpecialHandlingOffset;        /* Byte offset of the specialHandling
  173.                      * field in a Proc_ControlBlock. */
  174. MachStringTable    machMonBootParam;    /* Parameters from boot line. */
  175. /* 
  176.  * Pointer to the state structure for the current process and the
  177.  * current owner of the floating point unit.
  178.  */
  179. Mach_State    *machCurStatePtr = (Mach_State *)NIL;
  180. Mach_State    *machFPCurStatePtr = (Mach_State *)NIL;
  181.  
  182.  
  183. extern void PrintError _ARGS_((void));
  184. static void PrintInst _ARGS_((unsigned pc, unsigned inst));
  185. static void SoftFPReturn _ARGS_((void));
  186. static void MemErrorInterrupt _ARGS_((void));
  187.  
  188. ReturnStatus    (*machInterruptRoutines[MACH_NUM_HARD_INTERRUPTS]) _ARGS_((
  189.             unsigned int statusReg, unsigned int causeReg, 
  190.             Address pc, ClientData data));
  191. void        (*machIOInterruptRoutines[MACH_NUM_IO_SLOTS]) _ARGS_((
  192.             unsigned int statusReg, unsigned int causeReg, 
  193.             Address pc, ClientData data));
  194. ClientData    machIOInterruptArgs[MACH_NUM_IO_SLOTS];
  195. ClientData    machInterruptArgs[MACH_NUM_HARD_INTERRUPTS];
  196.  
  197. extern void Mach_KernGenException();
  198. extern void Mach_UserGenException();
  199. extern void VmMach_KernTLBException();
  200. extern void VmMach_TLBModException();
  201. extern void VmMach_UTLBMiss();
  202. extern void VmMach_EndUTLBMiss();
  203.  
  204. /*
  205.  * The kernel exception handlers.
  206.  */
  207. void (*machKernExcTable[])() = {
  208.     Mach_KernGenException,
  209.     VmMach_TLBModException,
  210.     VmMach_KernTLBException,
  211.     VmMach_KernTLBException,
  212.     Mach_KernGenException,
  213.     Mach_KernGenException,
  214.     Mach_KernGenException,
  215.     Mach_KernGenException,
  216.     Mach_KernGenException,
  217.     Mach_KernGenException,
  218.     Mach_KernGenException,
  219.     Mach_KernGenException,
  220.     Mach_KernGenException,
  221. };
  222.  
  223. /*
  224.  * The kernel exception handlers.
  225.  */
  226. void (*machUserExcTable[])() = {
  227.     Mach_UserGenException,
  228.     VmMach_TLBModException,
  229.     Mach_UserGenException,
  230.     Mach_UserGenException,
  231.     Mach_UserGenException,
  232.     Mach_UserGenException,
  233.     Mach_UserGenException,
  234.     Mach_UserGenException,
  235.     MachSysCall,
  236.     Mach_UserGenException,
  237.     Mach_UserGenException,
  238.     Mach_UserGenException,
  239.     Mach_UserGenException,
  240. };
  241.  
  242. /*
  243.  * Size of the instruction and data caches.
  244.  */
  245. unsigned    machDataCacheSize;
  246. unsigned    machInstCacheSize;
  247.  
  248. /*
  249.  * The debugger structure.
  250.  */
  251. Mach_DebugState    mach_DebugState;
  252. Mach_DebugState *machDebugStatePtr = &mach_DebugState;
  253.  
  254. static void SetupSigHandler _ARGS_((register Proc_ControlBlock *procPtr, 
  255.             register SignalStack *sigStackPtr, Address pc));
  256. static void ReturnFromSigHandler _ARGS_((register Proc_ControlBlock *procPtr));
  257. static ReturnStatus Interrupt _ARGS_((unsigned statusReg, unsigned causeReg, 
  258.             Address pc));
  259. static ReturnStatus MachStdHandler _ARGS_((unsigned int statusReg, 
  260.             unsigned int causeReg, Address pc, ClientData data));
  261. static ReturnStatus MachIOInterrupt _ARGS_((unsigned int statusReg, 
  262.             unsigned int causeReg, Address pc, ClientData data));
  263. static ReturnStatus MachMemInterrupt _ARGS_((unsigned int statusReg, 
  264.             unsigned int causeReg, Address pc, ClientData data));
  265. extern ReturnStatus MachFPInterrupt _ARGS_((unsigned int statusReg, 
  266.             unsigned int causeReg, Address pc, ClientData data));
  267.  
  268. /*
  269.  * Preallocate all machine state structs.
  270.  */
  271. Mach_State    machStateTable[VMMACH_MAX_KERN_STACKS];
  272. int        nextStateIndex = 0;
  273.  
  274. /*
  275.  *  Save the bad address that caused an exception. This makes debugging
  276.  *  of TLB misses easier.
  277.  */
  278.  
  279. Address        machBadVaddr = (Address) NIL;
  280.  
  281. /*
  282.  * Set to TRUE if we are inside of Mach_Probe.
  283.  */
  284.  
  285. Boolean        machInProbe = FALSE;
  286.  
  287. /*
  288.  * Read address of Mach_Probe.
  289.  */
  290.  
  291. Address        machProbeReadAddr = (Address) NIL;
  292. typedef struct trace {
  293.     char    *srcPtr;
  294.     char    *destPtr;
  295.     int        dest1;
  296.     int        dest2;
  297.     int        src;
  298. } Trace;
  299.  
  300. extern Trace *ncopyBuffer;
  301. extern int ncopyCount;
  302. extern int ncopyPath;
  303.  
  304. /*
  305.  * ----------------------------------------------------------------------------
  306.  *
  307.  * Mach_Init --
  308.  *
  309.  *    Initialize the exception vector table and some of the dispatching
  310.  *    tables.
  311.  *
  312.  * Results:
  313.  *    None.
  314.  *
  315.  * Side effects:
  316.  *    The exception vector table is initialized.
  317.  *
  318.  * ----------------------------------------------------------------------------
  319.  */
  320. void
  321. Mach_Init(boot_argc,boot_argv)
  322. int    boot_argc;    /* Argc from boot sequence. */
  323. MachStringTable    *boot_argv;    /* Boot sequence strings. */
  324. {
  325.     extern char end[], edata[];
  326.     int i;
  327.     char buf[256];
  328.     volatile unsigned int     *csrPtr = (unsigned int *) MACH_CSR_ADDR;
  329.     char    *copyPtr;
  330.  
  331.     /*
  332.      * Zero out the bss segment.
  333.      */
  334.     bzero(edata, end - edata);
  335.  
  336.     /*
  337.      * Set exported machine dependent variables.
  338.      */
  339.     mach_KernStart = (Address)MACH_KERN_START;
  340.     mach_KernEnd = (Address)MACH_KERN_END;
  341.     mach_CodeStart = (Address)MACH_CODE_START;
  342.     mach_StackBottom = (Address)MACH_STACK_BOTTOM;
  343.     mach_KernStackSize = MACH_KERN_STACK_SIZE;
  344.     mach_FirstUserAddr = (Address)MACH_FIRST_USER_ADDR;
  345.     mach_LastUserAddr = (Address)MACH_LAST_USER_ADDR;
  346.     mach_MaxUserStackAddr = (Address)MACH_MAX_USER_STACK_ADDR;
  347.     mach_LastUserStackPage = (MACH_MAX_USER_STACK_ADDR - 1) / VMMACH_PAGE_SIZE;
  348.  
  349.     /*
  350.      * Copy the boot parameter structure. The original location will get
  351.      * unmapped during vm initialization so we need to get our own copy.
  352.      * Depending on how the machine was booted, the boot arguments 
  353.      * may or may not be parsed.  So we'll glob them all together and
  354.      * then parse them.
  355.      */
  356.     buf[0] = '\0';
  357.     for (i = 0; i < boot_argc; i++) {
  358.     strcat(buf,boot_argv->argPtr[i]);
  359.     strcat(buf," ");
  360.     }
  361.     Mach_ArgParse(buf,&machMonBootParam);
  362.  
  363.     Mach_MonPrintf("Happy Birthday!!\n");
  364.     /*
  365.      * Get information on the memory bitmap.  This gets clobbered later.
  366.      */
  367.     /*
  368.      * IMPORTANT NOTE:  Don't use bcopy to do this, at least while
  369.      * bcopy contains the calls to Vm_CheckAccessible.  Those calls add a
  370.      * frame to the stack, causing it to overwrite the very information
  371.      * we're trying to copy.  JHH 4/18/91
  372.      */
  373.     copyPtr = Mach_MonGetenv("bitmaplen");
  374.     for(i = 0; i < sizeof(mach_BitmapLen); i++) {
  375.     mach_BitmapLen[i] = *copyPtr++;
  376.     }
  377.     copyPtr = Mach_MonGetenv("bitmap");
  378.     for(i = 0; i < sizeof(mach_BitmapAddr); i++) {
  379.     mach_BitmapAddr[i] = *copyPtr++;
  380.     }
  381.  
  382.     /*
  383.      * Set up the CSR.  Turn on memory ECC. Interrupts from IO slots are
  384.      * turned on as handlers are registered. 
  385.      */
  386.     *csrPtr = MACH_CSR_CORRECT;
  387.  
  388.  
  389.     /*
  390.      * Initialize some of the dispatching information.  The rest is
  391.      * initialized by Mach_InitSysCall below.
  392.      */
  393.     machMaxSysCall = -1;
  394.     machKcallTableOffset = (int) &((Proc_ControlBlock *) 0)->kcallTable;
  395.     machStatePtrOffset = (int) &((Proc_ControlBlock *) 0)->machStatePtr;
  396.     machSpecialHandlingOffset = (int) 
  397.                 &((Proc_ControlBlock *) 0)->specialHandling;
  398.  
  399.     /*
  400.      * We start off with interrupts disabled.
  401.      */
  402.     mach_NumDisableInterrupts[0] = 1;
  403.  
  404.     /*
  405.      * Copy down exception vector code.
  406.      */
  407.     if (F_TO_A VmMach_EndUTLBMiss - F_TO_A VmMach_UTLBMiss > 0x80) {
  408.     panic("Mach_Init: UTLB code too large\n");
  409.     }
  410.     bcopy(F_TO_A VmMach_UTLBMiss, F_TO_A MACH_UTLB_MISS_EXC_VEC,
  411.         F_TO_A VmMach_EndUTLBMiss - F_TO_A VmMach_UTLBMiss);
  412.     bcopy(F_TO_A MachException, (Address)MACH_GEN_EXC_VEC,
  413.           F_TO_A MachEndException - F_TO_A MachException);
  414.  
  415.     /*
  416.      * Set all interrupt handlers to a default, then install handlers for
  417.      * those interrupts processed by the mach module.
  418.      */
  419.     for (i = 0; i < MACH_NUM_HARD_INTERRUPTS; i++ ) {
  420.     Mach_SetHandler(i, MachStdHandler, (ClientData) i);
  421.     }
  422.     Mach_SetHandler(MACH_IO_INTR, MachIOInterrupt, NIL);
  423.     Mach_SetHandler(MACH_MEM_INTR, MachMemInterrupt, NIL);
  424.     Mach_SetHandler(MACH_FPU_INTR, MachFPInterrupt, NIL);
  425.  
  426.     /*
  427.      * Clear out the IO interrupt handlers.
  428.      */
  429.     for (i = 0; i < MACH_NUM_IO_SLOTS; i++ ) {
  430.     Mach_SetIOHandler(i, (void (*)()) NIL, (ClientData) NIL);
  431.     }
  432.     /*
  433.      * Enable the memory interrupt, because we need it for Mach_Probe to
  434.      * work.  Disabling interrupts has the side-effect of enabling the
  435.      * memory interrupt.
  436.      */
  437.     Mach_DisableIntr();
  438.     /*
  439.      * Clear out the i and d caches.
  440.      */
  441.     MachConfigCache();
  442.     MachFlushCache();
  443. }
  444.  
  445. /*
  446.  * ----------------------------------------------------------------------------
  447.  *
  448.  * Mach_SetHandler --
  449.  *
  450.  *    Register an interrupt handler for R3000 interrupts.  Interrupt
  451.  *    handlers are of the form:
  452.  *
  453.  *    void
  454.  *    Handler(statusReg, causeReg, pc, data)
  455.  *        unsigned int    statusReg;    Status register.
  456.  *        unsigned int    causeReg;    Cause register.
  457.  *        Address        pc;        PC where the interrupt 
  458.  *                        occurred.
  459.  *        ClientData    data        Callback data
  460.  *    
  461.  *
  462.  * Results:
  463.  *     None.
  464.  *
  465.  * Side effects:
  466.  *     The interrupt handling table is modified.
  467.  *
  468.  * ----------------------------------------------------------------------------
  469.  */
  470.  
  471. void
  472. Mach_SetHandler(level, handler, clientData)
  473.     int level;            /* Interrupt level. */
  474.     ReturnStatus (*handler) _ARGS_((unsigned int statusReg, 
  475.                 unsigned int causeReg,
  476.                 Address pc, ClientData data)); 
  477.                     /* Interrupt handler. */
  478.     ClientData    clientData;     /* Data to pass handler. */
  479. {
  480.     /*
  481.      * Check that it is valid.  
  482.      */
  483.     if ((level < 0) || (level >= MACH_NUM_HARD_INTERRUPTS)){
  484.     panic("Warning: Bad interrupt level %d\n", level);
  485.     } else {
  486.     machInterruptRoutines[level] = handler;
  487.     machInterruptArgs[level] = clientData;
  488.     }
  489. }
  490.  
  491. /*
  492.  *----------------------------------------------------------------------
  493.  *
  494.  * MachStdHandler --
  495.  *
  496.  *    The default handler for hard interrupts.
  497.  *
  498.  * Results:
  499.  *    None.
  500.  *
  501.  * Side effects:
  502.  *    Prints out an error message.
  503.  *
  504.  *----------------------------------------------------------------------
  505.  */
  506. /*ARGSUSED*/
  507. static ReturnStatus
  508. MachStdHandler(statusReg, causeReg, pc, data)
  509.     unsigned int    statusReg;    /* Status register. */
  510.     unsigned int    causeReg;    /* Cause register. */
  511.     Address        pc;        /* PC. */
  512.     ClientData        data;        /* Interrupt level. */
  513. {
  514.     int        level;
  515.  
  516.     level = (int) data;
  517.     printf("WARNING: no handler for level %d interrupt!\n", level);
  518.     return MACH_OK;
  519. }
  520.  
  521. /*
  522.  * ----------------------------------------------------------------------------
  523.  *
  524.  * Mach_SetIOHandler --
  525.  *
  526.  *    Register an interrupt handler for IO device interrupts.  All IO
  527.  *    device interrupts are merged into the same R3000 interrupt
  528.  *    (level 0). Interrupt handlers are of the form:
  529.  *
  530.  *    void
  531.  *    Handler(data)
  532.  *        ClientData    data        Callback data
  533.  *
  534.  * Results:
  535.  *     None.
  536.  *
  537.  * Side effects:
  538.  *     The IO interrupt handling table is modified.  If the handler is not
  539.  *    NIL then the IO interrupt for the slot is turned on in the CSR.
  540.  *
  541.  * ----------------------------------------------------------------------------
  542.  */
  543.  
  544. void
  545. Mach_SetIOHandler(slot, handler, clientData)
  546.     int slot;            /* Interrupt number to set */
  547.     void (*handler) _ARGS_((ClientData data)); /* Interrupt handler. */
  548.     ClientData    clientData;     /* Data to pass handler. */
  549. {
  550.     volatile unsigned int     *csrPtr = (unsigned int *) MACH_CSR_ADDR;
  551.     unsigned int        mask;
  552.     /*
  553.      * Check that it is valid.  
  554.      */
  555.     if ((slot < 0) || (slot >= MACH_NUM_IO_SLOTS)){
  556.     panic("Warning: Bad slot number %d\n",slot);
  557.     } else {
  558.     if ((machIOInterruptRoutines[slot] != (void (*)()) NIL) &&
  559.         (handler != (void (*)()) NIL)) {
  560.         Mach_MonPrintf("WARNING: replacing existing handler for slot %d.\n",
  561.         slot);
  562.     }
  563.     machIOInterruptRoutines[slot] = handler;
  564.     machIOInterruptArgs[slot] = clientData;
  565.     if (handler != (void (*)()) NIL) {
  566.         mask = ((1 << slot) << MACH_CSR_IOINTEN_SHIFT);
  567.         if (!(mask & MACH_CSR_IOINTEN)) {
  568.         panic("Goof up computing interrupt enable bits in csr.\n");
  569.         }
  570.         *csrPtr |= mask;
  571.     }
  572.     }
  573. }
  574.  
  575. static Vm_ProcInfo    mainProcInfo;
  576. static Mach_State    mainMachState;
  577. static VmMach_ProcData    mainProcData;
  578.  
  579. /*
  580.  *----------------------------------------------------------------------
  581.  *
  582.  * Mach_InitFirstProc --
  583.  *
  584.  *    Initialize the machine state struct for the very first process.
  585.  *
  586.  * Results:
  587.  *    None.
  588.  *
  589.  * Side effects:
  590.  *    Machine info allocated and stack start set up.
  591.  *
  592.  *----------------------------------------------------------------------
  593.  */
  594. void
  595. Mach_InitFirstProc(procPtr)
  596.     Proc_ControlBlock    *procPtr;
  597. {
  598.  
  599.     assert(offsetof(Proc_ControlBlock, unixErrno) == MACH_UNIX_ERRNO_OFFSET);
  600.     procPtr->machStatePtr = &mainMachState;
  601.     procPtr->machStatePtr->kernStackStart = mach_StackBottom;
  602.     procPtr->machStatePtr->kernStackEnd = 
  603.                 (mach_StackBottom + mach_KernStackSize);
  604.     /*
  605.      * Set up the TLB entries.  This code depends
  606.      * implictly upon MACH_KERN_STACK_PAGES.
  607.      */
  608.     procPtr->machStatePtr->tlbHighEntry  = 0;
  609.     procPtr->machStatePtr->tlbLowEntries[0] = 0;
  610.     procPtr->machStatePtr->tlbLowEntries[1] = 0;
  611.     procPtr->machStatePtr->tlbLowEntries[2] = 0;
  612.     procPtr->vmPtr = &mainProcInfo;
  613.     procPtr->vmPtr->machPtr = &mainProcData;
  614.     VmMach_ProcInit(&mainProcInfo);
  615.     machCurStatePtr = procPtr->machStatePtr;
  616.     VmMach_SetupContext(procPtr);
  617. }
  618.  
  619.  
  620. /*
  621.  *----------------------------------------------------------------------
  622.  *
  623.  * Mach_SetupNewState --
  624.  *
  625.  *    Initialize the machine state for this process.  This includes 
  626.  *    allocating and initializing a kernel stack.  Assumed that will
  627.  *    be called when starting a process after a fork or restarting a
  628.  *    process after a migration.
  629.  *
  630.  * Results:
  631.  *    PROC_NO_STACKS if couldn't allocate a kernel stack.  SUCCESS otherwise.
  632.  *
  633.  * Side effects:
  634.  *    Machine state in the destination process control block is overwritten.
  635.  *
  636.  *----------------------------------------------------------------------
  637.  */ 
  638. ReturnStatus
  639. Mach_SetupNewState(procPtr, fromStatePtr, startFunc, startPC, user)
  640.     Proc_ControlBlock    *procPtr;    /* Pointer to process control block
  641.                      * to initialize state for. */
  642.     Mach_State        *fromStatePtr;    /* State of parent on fork or from
  643.                      * other machine on migration. */
  644.     void        (*startFunc)();    /* Function to call when process first
  645.                      * starts executing. */
  646.     Address        startPC;    /* Address to pass as argument to 
  647.                      * startFunc.  If NIL then the address
  648.                      * is taken from *fromStatePtr's 
  649.                      * exception stack. */
  650.     Boolean        user;        /* TRUE if is a user process. */
  651. {
  652.     register    KernelStack    *stackPtr;
  653.     register    Mach_State    *statePtr;
  654.     unsigned            virtPage;
  655.  
  656.     if (procPtr->machStatePtr == (Mach_State *)NIL) {
  657.     procPtr->machStatePtr = &machStateTable[nextStateIndex];
  658.     nextStateIndex++;
  659.     if (nextStateIndex >= VMMACH_MAX_KERN_STACKS) {
  660.         panic("Mach_SetupNewState: Out of machine state structs\n");
  661.     }
  662.     }
  663.  
  664.     statePtr = procPtr->machStatePtr;
  665.     /* 
  666.      * Allocate a kernel stack for this process.
  667.      */
  668.     statePtr->kernStackStart = Vm_GetKernelStack(0);
  669.     if (statePtr->kernStackStart == (Address)NIL) {
  670.     return(PROC_NO_STACKS);
  671.     }
  672.     statePtr->kernStackEnd = statePtr->kernStackStart + MACH_KERN_STACK_SIZE;
  673.     /*
  674.      * Set up the TLB entries.  This code depends
  675.      * implictly upon MACH_KERN_STACK_PAGES.
  676.      */
  677.     virtPage = (unsigned)(statePtr->kernStackStart + VMMACH_PAGE_SIZE) >>
  678.                             VMMACH_PAGE_SHIFT;
  679.     statePtr->tlbHighEntry = (virtPage << VMMACH_TLB_VIRT_PAGE_SHIFT) |
  680.                  (VMMACH_KERN_PID << VMMACH_TLB_PID_SHIFT);
  681.     virtPage -= VMMACH_VIRT_CACHED_START_PAGE;
  682.     statePtr->tlbLowEntries[0] = vmMach_KernelTLBMap[virtPage];
  683.     statePtr->tlbLowEntries[1] = vmMach_KernelTLBMap[virtPage + 1];
  684.     statePtr->tlbLowEntries[2] = vmMach_KernelTLBMap[virtPage + 2];
  685.  
  686.     statePtr->switchRegState.regs[SP] =
  687.             (unsigned)(statePtr->kernStackEnd - sizeof(KernelStack));
  688.     /*
  689.      * Initialize the stack so that it looks like it is in the middle of
  690.      * Mach_ContextSwitch.
  691.      */
  692.     stackPtr = (KernelStack *)(statePtr->switchRegState.regs[SP]);
  693.     stackPtr->magicNumber = MAGIC;
  694.     stackPtr->statusReg = 0;
  695.     statePtr->switchRegState.regs[RA] = (unsigned)startFunc;
  696.     /*
  697.      * Set up the user's stack pointer.
  698.      */
  699.     statePtr->userState.regState.regs[SP] = (unsigned)mach_MaxUserStackAddr;
  700.     /* 
  701.      * Set up the state of the process.  User processes inherit from their
  702.      * parent or the migrated process.  If the PC is not specified, take it
  703.      * from the parent as well.
  704.      */
  705.     if (user) {
  706.     bcopy((Address)&fromStatePtr->userState,
  707.           (Address)&statePtr->userState,
  708.           sizeof(statePtr->userState));
  709.     statePtr->userState.regState.pc += 4;
  710.     }
  711.     if (startPC == (Address)NIL) {
  712.     statePtr->switchRegState.regs[A0] = 
  713.             (unsigned)fromStatePtr->userState.regState.pc + 4;
  714.     } else {
  715.     statePtr->switchRegState.regs[A0] = (unsigned)startPC;
  716.     }
  717.     statePtr->userState.regState.fpStatusReg = 0;
  718.  
  719.     return(SUCCESS);
  720. }
  721.  
  722. /*
  723.  *----------------------------------------------------------------------
  724.  *
  725.  * Mach_SetReturnVal --
  726.  *
  727.  *    Set the return value for a process from a system call.  Intended to
  728.  *    be called by the routine that starts a user process after a fork.
  729.  *
  730.  * Results:
  731.  *    None.
  732.  *
  733.  * Side effects:
  734.  *    Register D0 is set in the user registers.
  735.  *
  736.  *----------------------------------------------------------------------
  737.  */ 
  738. void
  739. Mach_SetReturnVal(procPtr, retVal, retVal2)
  740.     Proc_ControlBlock    *procPtr;    /* Process to set return value for. */
  741.     int            retVal;        /* Value for process to return. */
  742.     int            retVal2;    /* Second return value. */
  743. {
  744.     procPtr->machStatePtr->userState.regState.regs[V0] = (unsigned)retVal;
  745.     procPtr->machStatePtr->userState.regState.regs[V1] = (unsigned)retVal2;
  746. }
  747.  
  748. /*----------------------------------------------------------------------------
  749.  *
  750.  * Mach_Return2 --
  751.  *
  752.  *      Set the second return value for Unix compat. routines that
  753.  *      return two values.
  754.  *
  755.  * Results:
  756.  *      None.
  757.  *
  758.  * Side effects:
  759.  *      v1 <- val
  760.  *
  761.  *----------------------------------------------------------------------------
  762.  */
  763. void
  764. Mach_Return2(val)
  765. int val;
  766. {
  767.     Proc_GetActualProc()->machStatePtr->userState.regState.regs[V1] =
  768.         (unsigned)val;
  769. }
  770.  
  771. /*
  772.  *----------------------------------------------------------------------
  773.  *
  774.  * Mach_StartUserProc --
  775.  *
  776.  *    Start a user process executing for the first time.
  777.  *
  778.  * Results:
  779.  *    None.
  780.  *
  781.  * Side effects:
  782.  *    Stack pointer and the program counter set for the process and
  783.  *    the current process's image is replaced.
  784.  *
  785.  *----------------------------------------------------------------------
  786.  */
  787. void
  788. Mach_StartUserProc(procPtr, entryPoint)
  789.     Proc_ControlBlock    *procPtr;    /* Process control block for process
  790.                      * to start. */
  791.     Address        entryPoint;    /* Where process is to start
  792.                      * executing. */
  793. {
  794.     register    Mach_State    *statePtr;
  795.  
  796.     statePtr = procPtr->machStatePtr;
  797.     statePtr->userState.regState.pc = entryPoint;
  798.     (void)MachUserReturn(procPtr);
  799.  
  800.     MachRunUserProc(entryPoint, statePtr->userState.regState.regs[SP]);
  801.     /* THIS DOES NOT RETURN */
  802. }
  803.  
  804.  
  805. /*
  806.  *----------------------------------------------------------------------
  807.  *
  808.  * Mach_ExecUserProc --
  809.  *
  810.  *    Replace the calling user process's image with a new one.
  811.  *
  812.  * Results:
  813.  *    None.
  814.  *
  815.  * Side effects:
  816.  *    Stack pointer set for the process.
  817.  *
  818.  *----------------------------------------------------------------------
  819.  */
  820. void
  821. Mach_ExecUserProc(procPtr, userStackPtr, entryPoint)
  822.     Proc_ControlBlock    *procPtr;        /* Process control block for
  823.                          * process to exec. */
  824.     Address        userStackPtr;    /* Stack pointer for when the
  825.                          * user process resumes 
  826.                          * execution. */
  827.     Address        entryPoint;        /* Where the user process is
  828.                          * to resume execution. */
  829. {
  830.     procPtr->machStatePtr->userState.regState.regs[SP] =
  831.                         (unsigned)userStackPtr;
  832.     Mach_StartUserProc(procPtr, entryPoint);
  833.     /* THIS DOES NOT RETURN */
  834. }
  835.  
  836. /*
  837.  *----------------------------------------------------------------------
  838.  *
  839.  * Mach_FreeState --
  840.  *
  841.  *    Free up the machine state for the given process control block.
  842.  *
  843.  * Results:
  844.  *    None.
  845.  *
  846.  * Side effects:
  847.  *    Free up the kernel stack.
  848.  *
  849.  *----------------------------------------------------------------------
  850.  */
  851. void
  852. Mach_FreeState(procPtr)
  853.     Proc_ControlBlock    *procPtr;    /* Process control block to free
  854.                      * machine state for. */
  855. {
  856.     if (procPtr->machStatePtr->kernStackStart != (Address)NIL) {
  857.     Vm_FreeKernelStack(procPtr->machStatePtr->kernStackStart);
  858.     procPtr->machStatePtr->kernStackStart = (Address)NIL;
  859.     }
  860.     if (procPtr->machStatePtr == machFPCurStatePtr) {
  861.     machFPCurStatePtr = (Mach_State *)NIL;
  862.     }
  863. }
  864.  
  865.  
  866. /*
  867.  *----------------------------------------------------------------------
  868.  *
  869.  * Mach_CopyState --
  870.  *
  871.  *    Copy the state from the given state structure to the machine
  872.  *    state structure for the destination process control block.  Intended
  873.  *    to be used by the debugger to modify the state.The only fields
  874.  *    that can be modified are the following:
  875.  *
  876.  *        1) user stack pointer
  877.  *        2) all trap registers except for the stack pointer because the
  878.  *           stack pointer in the trap registers is the kernel stack pointer.
  879.  *        3) the PC, VOR and status register in the exception stack.
  880.  *
  881.  * Results:
  882.  *    None.
  883.  *
  884.  * Side effects:
  885.  *    Machine state in the destination process control block is overwritten.
  886.  *
  887.  *----------------------------------------------------------------------
  888.  */ 
  889. void
  890. Mach_CopyState(statePtr, destProcPtr)
  891.     Mach_State        *statePtr;    /* Pointer to state to copy from. */
  892.     Proc_ControlBlock    *destProcPtr;    /* Process control block to copy
  893.                      * state to. */
  894. {
  895.     bcopy((Address)&statePtr->userState,
  896.           (Address)&destProcPtr->machStatePtr->userState,
  897.           sizeof(statePtr->userState));
  898. }
  899.  
  900.  
  901. /*
  902.  *----------------------------------------------------------------------
  903.  *
  904.  * Mach_GetDebugState --
  905.  *
  906.  *    Extract the appropriate fields from the machine state struct
  907.  *    and store them into the debug struct.
  908.  *
  909.  * Results:
  910.  *    None.
  911.  *
  912.  * Side effects:
  913.  *    Debug struct filled in from machine state struct.
  914.  *
  915.  *----------------------------------------------------------------------
  916.  */ 
  917. void
  918. Mach_GetDebugState(procPtr, debugStatePtr)
  919.     Proc_ControlBlock    *procPtr;
  920.     Proc_DebugState    *debugStatePtr;
  921. {
  922.     register    Mach_State    *machStatePtr;
  923.  
  924.     machStatePtr = procPtr->machStatePtr;
  925.     bcopy((Address)machStatePtr->userState.regState.regs,
  926.           (Address)debugStatePtr->regState.regs,
  927.           sizeof(machStatePtr->userState.regState.regs));
  928.     debugStatePtr->regState.pc = machStatePtr->userState.regState.pc;
  929. }
  930.  
  931.  
  932. /*
  933.  *----------------------------------------------------------------------
  934.  *
  935.  * Mach_SetDebugState --
  936.  *
  937.  *    Extract the appropriate fields from the debug struct
  938.  *    and store them into the machine state struct.
  939.  *
  940.  * Results:
  941.  *    None.
  942.  *
  943.  * Side effects:
  944.  *    Machine state struct filled in from the debug state struct.
  945.  *
  946.  *----------------------------------------------------------------------
  947.  */ 
  948. void
  949. Mach_SetDebugState(procPtr, debugStatePtr)
  950.     Proc_ControlBlock    *procPtr;
  951.     Proc_DebugState    *debugStatePtr;
  952. {
  953.     register    Mach_State    *machStatePtr;
  954.  
  955.     machStatePtr = procPtr->machStatePtr;
  956.     bcopy((Address)debugStatePtr->regState.regs,
  957.           (Address)machStatePtr->userState.regState.regs,
  958.           sizeof(machStatePtr->userState.regState.regs));
  959.     machStatePtr->userState.regState.pc = debugStatePtr->regState.pc;
  960. }
  961.  
  962.  
  963. /*
  964.  * ----------------------------------------------------------------------------
  965.  *
  966.  * Mach_GetUserStackPtr --
  967.  *
  968.  *    Return the user stack pointer from the machine state struct for the
  969.  *    given process.
  970.  *
  971.  * Results:
  972.  *    The value of the user stack pointer when the process trapped.
  973.  *
  974.  * Side effects:
  975.  *    None.
  976.  *
  977.  * ----------------------------------------------------------------------------
  978.  */
  979. Address
  980. Mach_GetUserStackPtr(procPtr)
  981.     Proc_ControlBlock    *procPtr;
  982. {
  983.     return((Address)procPtr->machStatePtr->userState.regState.regs[SP]);
  984. }
  985.  
  986.  
  987. /*
  988.  * ----------------------------------------------------------------------------
  989.  *
  990.  * Mach_GetStackPointer --
  991.  *
  992.  *    Return the value of the stack pointer.
  993.  *
  994.  * Results:
  995.  *    The value of the user's stack pointer.
  996.  *
  997.  * Side effects:
  998.  *    None.
  999.  *
  1000.  * ----------------------------------------------------------------------------
  1001.  */
  1002. Address
  1003. Mach_GetStackPointer(procPtr)
  1004.     Proc_ControlBlock    *procPtr;
  1005. {
  1006.     return((Address)procPtr->machStatePtr->userState.regState.regs[SP]);
  1007. }
  1008.  
  1009.  
  1010. /*
  1011.  *----------------------------------------------------------------------
  1012.  *
  1013.  * Mach_InitSyscall --
  1014.  *
  1015.  *    During initialization, this procedure is called once for each
  1016.  *    kernel call, in order to set up information used to dispatch
  1017.  *    the kernel call.  This procedure must be called once for each
  1018.  *    kernel call, in order starting at 0.
  1019.  *
  1020.  * Results:
  1021.  *    None.
  1022.  *
  1023.  * Side effects:
  1024.  *    Initializes the dispatch tables for the kernel call.
  1025.  *
  1026.  *----------------------------------------------------------------------
  1027.  */
  1028. void
  1029. Mach_InitSyscall(callNum, numArgs, normalHandler, migratedHandler)
  1030.     int callNum;            /* Number of the system call. */
  1031.     int numArgs;            /* Number of one-word arguments passed
  1032.                      * into call on stack. */
  1033.     ReturnStatus (*normalHandler)();    /* Procedure to process kernel call
  1034.                      * when process isn't migrated. */
  1035.     ReturnStatus (*migratedHandler)();    /* Procedure to process kernel call
  1036.                      * for migrated processes. */
  1037. {
  1038.     machMaxSysCall++;
  1039.     if (machMaxSysCall != callNum) {
  1040.     printf("Warning: out-of-order kernel call initialization, call %d\n",
  1041.            callNum);
  1042.     }
  1043.     if (machMaxSysCall >= MAXCALLS) {
  1044.     printf("Warning: too many kernel calls.\n");
  1045.     machMaxSysCall--;
  1046.     return;
  1047.     }
  1048.     if (numArgs > MAXARGS) {
  1049.     printf("Warning: too many arguments to kernel call %d\n", callNum);
  1050.     numArgs = MAXARGS;
  1051.     }
  1052.     machArgDispatch[machMaxSysCall] = machArgDispatchTable[numArgs];
  1053.     mach_NormalHandlers[machMaxSysCall] = normalHandler;
  1054.     mach_MigratedHandlers[machMaxSysCall] = migratedHandler;
  1055. }
  1056.  
  1057.  
  1058. /*
  1059.  * ----------------------------------------------------------------------------
  1060.  *
  1061.  * MachUserExceptionHandler --
  1062.  *
  1063.  *      Handle a user exception.
  1064.  *
  1065.  * Results:
  1066.  *      TRUE if should enable the floating point coprocessor.
  1067.  *
  1068.  * Side effects:
  1069.  *      None.
  1070.  *
  1071.  * ----------------------------------------------------------------------------
  1072.  */
  1073. Boolean
  1074. MachUserExceptionHandler(statusReg, causeReg, badVaddr, pc)
  1075.     unsigned    statusReg;    /* The status register at the time of the
  1076.                  * exception. */
  1077.     unsigned    causeReg;    /* The cause register - contains the type
  1078.                  * of exception. */
  1079.     Address    badVaddr;    /* The address (if any) that the fault
  1080.                  * occured on. */
  1081.     Address    pc;        /* Program counter where to continue. */
  1082. {
  1083.     register    Proc_ControlBlock    *procPtr;
  1084.     int                    cause;
  1085.     Boolean                retVal;
  1086.     ReturnStatus            status;
  1087.  
  1088.     machBadVaddr = badVaddr;
  1089.     cause = (causeReg & MACH_CR_EXC_CODE) >> MACH_CR_EXC_CODE_SHIFT;
  1090.     if (cause != MACH_EXC_INT) {
  1091.     Mach_EnableIntr();
  1092.     }
  1093.  
  1094.     procPtr = Proc_GetActualProc();
  1095.     switch (cause) {
  1096.     case MACH_EXC_INT:
  1097.         status = Interrupt(statusReg, causeReg, pc);
  1098.         if (status != MACH_OK) {
  1099.         panic("MachUserExceptionHandler: nested interrupts.\n");
  1100.         }
  1101.         /* 
  1102.          * Enable interrupts so that we can do the user mode return
  1103.          * checks.
  1104.          */
  1105.         Mach_EnableIntr();
  1106.         break;
  1107.     case MACH_EXC_TLB_MOD:
  1108.         if (VmMach_TLBModFault(badVaddr) != SUCCESS) {
  1109.         printf("Protection fault in process %x: pc=%x addr=%x\n",
  1110.             procPtr->processID, pc, badVaddr);
  1111.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  1112.                 procPtr->processID, FALSE, badVaddr);
  1113.         }
  1114.         break;
  1115.     case MACH_EXC_TLB_LD_MISS:
  1116.     case MACH_EXC_TLB_ST_MISS:
  1117.         if (VmMach_TLBFault(badVaddr) != SUCCESS) {
  1118.         printf("Bad user TLB fault in process %x: pc=%x addr=%x\n",
  1119.             procPtr->processID, pc, badVaddr);
  1120.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  1121.                 procPtr->processID, FALSE, badVaddr);
  1122.         }
  1123.         break;
  1124.     case MACH_EXC_ADDR_ERR_LD:
  1125.     case MACH_EXC_ADDR_ERR_ST:
  1126.         printf("Address fault in process %x: pc=%x addr=%x\n",
  1127.             procPtr->processID, pc, badVaddr);
  1128.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  1129.                 procPtr->processID, FALSE, badVaddr);
  1130.         break;
  1131.     case MACH_EXC_BUS_ERR_IFETCH:
  1132.         printf("MachExceptionHandler: User bus error on ifetch");
  1133.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  1134.                 procPtr->processID, FALSE, badVaddr);
  1135.         break;
  1136.     case MACH_EXC_BUS_ERR_LD_ST:
  1137.         printf("MachExceptionHandler: User bus error on ld or st");
  1138.         (void) Sig_Send(SIG_ADDR_FAULT, SIG_ACCESS_VIOL, 
  1139.                 procPtr->processID, FALSE, badVaddr);
  1140.         break;
  1141.     case MACH_EXC_SYSCALL:
  1142.         if (!MachUNIXSyscall()) {
  1143.         printf("MachExceptionHandler: Bad syscall magic for proc %x\n",
  1144.                             procPtr->processID);
  1145.         (void) Sig_Send(SIG_ILL_INST, SIG_BAD_TRAP,
  1146.                 procPtr->processID, FALSE, pc);
  1147.         }
  1148.         break;
  1149.     case MACH_EXC_BREAK: {
  1150.         unsigned inst;
  1151.         /*
  1152.          * Check to see if this is a return from signal handler
  1153.          * break or a normal breakpoint.
  1154.          */
  1155.         if (Vm_CopyIn(sizeof(int), pc, (Address)&inst) != SUCCESS) {
  1156.         panic("MachExceptionHandler: Couldn't fetch break inst.");
  1157.         }
  1158. #if 0
  1159.         printf("Pc = 0x%x, Instruction = 0x%x\n", pc, inst);
  1160.         printf("Cause register = 0x%x\n", causeReg);
  1161. #endif
  1162.         switch ((int)(inst & MACH_BREAK_CODE_FIELD)) {
  1163.         case MACH_BREAKPOINT_VAL:
  1164.             Proc_Lock(procPtr);
  1165.             if (procPtr->genFlags & PROC_DEBUG_ON_EXEC) {
  1166.             procPtr->genFlags &= ~PROC_DEBUG_ON_EXEC;
  1167.             (void) Sig_SendProc(procPtr, SIG_DEBUG, 
  1168.                         SIG_NO_CODE, pc);
  1169.             } else {
  1170.             (void) Sig_SendProc(procPtr, SIG_BREAKPOINT, 
  1171.                         SIG_NO_CODE, pc);
  1172.             }
  1173.             Proc_Unlock(procPtr);
  1174.             break;
  1175.         case MACH_SSTEP_VAL: {
  1176.             ReturnStatus    status;
  1177.  
  1178.             Vm_ChangeCodeProt(procPtr, pc, 4, TRUE);
  1179.             status = Vm_CopyOut(4, (Address)&machCurStatePtr->sstepInst,                    pc);
  1180.             Vm_ChangeCodeProt(procPtr, pc, 4, FALSE);
  1181.             Vm_FlushCode(procPtr, pc, 4);
  1182.             if (status != SUCCESS) {
  1183.             panic("MachUserExceptionHandler: Bad sstep PC\n");
  1184.             }
  1185.             Proc_Lock(procPtr);
  1186.             (void) Sig_SendProc(procPtr, SIG_TRACE_TRAP, SIG_NO_CODE,
  1187.                 pc);
  1188.             Proc_Unlock(procPtr);
  1189.             break;
  1190.         }
  1191.  
  1192.         case MACH_SIG_RET_VAL:
  1193.             ReturnFromSigHandler(procPtr);
  1194.             break;
  1195.         default:
  1196.             printf("Bogus bp-trap\n");
  1197.             (void) Sig_Send(SIG_ILL_INST, SIG_ILL_INST_CODE,
  1198.                     procPtr->processID, FALSE, pc);
  1199.             break;
  1200.         }
  1201.         break;
  1202.     }
  1203.     case MACH_EXC_RES_INST:
  1204.         printf("Reserved instruction in process %x at pc=%x\n",
  1205.             procPtr->processID, pc);
  1206.         (void) Sig_Send(SIG_ILL_INST, SIG_ILL_INST_CODE,
  1207.                 procPtr->processID, FALSE, pc);
  1208.         break;
  1209.     case MACH_EXC_COP_UNUSABLE:
  1210.         MachSwitchFPState(machFPCurStatePtr, machCurStatePtr);
  1211.         machFPCurStatePtr = machCurStatePtr;
  1212.         break;
  1213.     case MACH_EXC_OVFLOW:
  1214.         printf("Overflow exception in process %x at pc=%x\n",
  1215.             procPtr->processID, pc);
  1216.         (void) Sig_Send(SIG_ARITH_FAULT, SIG_OVERFLOW,
  1217.                 procPtr->processID, FALSE, pc);
  1218.         break;
  1219.     }
  1220.     retVal = MachUserReturn(procPtr);
  1221.  
  1222.     return(retVal);
  1223. }
  1224.  
  1225.  
  1226. /*
  1227.  * ----------------------------------------------------------------------------
  1228.  *
  1229.  * MachKernelExceptionHandler --
  1230.  *
  1231.  *      Handle a kernel exception.
  1232.  *
  1233.  * Results:
  1234.  *      MACH_KERN_ERROR if the debugger should be called after this routine 
  1235.  *    returns, MACH_USER_ERROR if a copy to/from user space caused an 
  1236.  *    unrecoverable bus error, and MACH_OK if everything worked out ok.
  1237.  *
  1238.  * Side effects:
  1239.  *      None.
  1240.  *
  1241.  * ----------------------------------------------------------------------------
  1242.  */
  1243. int
  1244. MachKernelExceptionHandler(statusReg, causeReg, badVaddr, pc)
  1245.     unsigned    statusReg;    /* The status register at the time of the
  1246.                  * exception. */
  1247.     unsigned    causeReg;    /* The cause register - contains the type
  1248.                  * of exception. */
  1249.     Address    badVaddr;    /* The address (if any) that the fault
  1250.                  * occured on. */
  1251.     Address    pc;        /* Program counter where to continue. */
  1252. {
  1253.     register    Proc_ControlBlock    *procPtr;
  1254.     ReturnStatus            status;
  1255.     int                    cause;
  1256.  
  1257.     cause = (causeReg & MACH_CR_EXC_CODE) >> MACH_CR_EXC_CODE_SHIFT;
  1258.     machBadVaddr = badVaddr;
  1259.  
  1260.     /*
  1261.      * Process kernel traps.
  1262.      */
  1263.     procPtr = Proc_GetActualProc();
  1264.     switch (cause) {
  1265.     case MACH_EXC_INT:
  1266.         status = Interrupt(statusReg, causeReg, pc);
  1267.         return(status);
  1268.     case MACH_EXC_TLB_LD_MISS:
  1269.     case MACH_EXC_TLB_ST_MISS:
  1270.     case MACH_EXC_TLB_MOD: {
  1271.         Boolean    copyInProgress = FALSE;
  1272.  
  1273.         if (statusReg & MACH_SR_INT_ENA_PREV) {
  1274.         /*
  1275.          * Enable interrupts.
  1276.          */
  1277.         Mach_EnableIntr();
  1278.         }
  1279.  
  1280.         if (pc >= F_TO_A Vm_CopyIn && pc < F_TO_A VmMachCopyEnd) {
  1281.         copyInProgress = TRUE;
  1282.         } else if (pc >= F_TO_A MachFetchArgs &&
  1283.                    pc <= F_TO_A MachFetchArgsEnd) {
  1284.         copyInProgress = TRUE;
  1285.         } else if (badVaddr < (Address)VMMACH_VIRT_CACHED_START &&
  1286.                (badVaddr >= (Address)VMMACH_PHYS_CACHED_START ||
  1287.             procPtr == (Proc_ControlBlock *)NIL ||
  1288.             procPtr->vmPtr->numMakeAcc == 0)) {
  1289.         if (procPtr != (Proc_ControlBlock *)NIL) {
  1290.             printf("procPtr->vmPtr->numMakeAcc = %d\n", 
  1291.             procPtr->vmPtr->numMakeAcc);
  1292.         }
  1293.         return(MACH_KERN_ERROR);
  1294.         }
  1295.         if (((causeReg & MACH_CR_EXC_CODE) >> 
  1296.             MACH_CR_EXC_CODE_SHIFT) == MACH_EXC_TLB_MOD) {
  1297.         status = VmMach_TLBModFault(badVaddr);
  1298.         } else {
  1299.         status = VmMach_TLBFault(badVaddr);
  1300.         }
  1301.         if (status != SUCCESS) {
  1302.         if (copyInProgress) {
  1303.             return(MACH_USER_ERROR);
  1304.         } else {
  1305.             printf("badVaddr = 0x%x\n", badVaddr);
  1306.             return(MACH_KERN_ERROR);
  1307.         }
  1308.         } else {
  1309.         return(MACH_OK);
  1310.         }
  1311.     }
  1312.  
  1313.     case MACH_EXC_ADDR_ERR_LD:
  1314.         printf("MachKernelExceptionHandler: %s: addr: %x PC: %x\n",
  1315.             "Address error on load", badVaddr, pc);
  1316.         return(MACH_KERN_ERROR);
  1317.     case MACH_EXC_ADDR_ERR_ST:
  1318.         printf("MachKernelExceptionHandler:  Address error on store\n");
  1319.         return(MACH_KERN_ERROR);
  1320.     case MACH_EXC_BUS_ERR_IFETCH:
  1321.         printf("MachKernelExceptionHandler:  Bus error on ifetch\n");
  1322.         return(MACH_KERN_ERROR);
  1323.     case MACH_EXC_BUS_ERR_LD_ST:
  1324.         if (machInProbe) {
  1325.         return(MACH_OK);
  1326.         }
  1327.         printf("MachKernelExceptionHandler:  Bus error on load or store\n");
  1328.         return(MACH_KERN_ERROR);
  1329.     case MACH_EXC_SYSCALL:
  1330.         printf("MachKernelExceptionHandler:  System call in kernel mode\n");
  1331.         return(MACH_KERN_ERROR);
  1332.     case MACH_EXC_BREAK:
  1333.         return(MACH_KERN_ERROR);
  1334.     case MACH_EXC_RES_INST:
  1335.         printf("MachKernelExceptionHandler:  Reserved instruction\n");
  1336.         return(MACH_KERN_ERROR);
  1337.     case MACH_EXC_COP_UNUSABLE:
  1338.         printf("MachKernelExceptionHandler:  Coprocessor unusable\n");
  1339.         return(MACH_KERN_ERROR);
  1340.     case MACH_EXC_OVFLOW:
  1341.         printf("MachKernelExceptionHandler:  Overflow\n");
  1342.         return(MACH_KERN_ERROR);
  1343.     default:
  1344.         printf("MachKernelExceptionHandler: Unknown exception\n");
  1345.         return(MACH_KERN_ERROR);
  1346.     }
  1347. }
  1348.  
  1349.  
  1350. /*
  1351.  * ----------------------------------------------------------------------------
  1352.  *
  1353.  * Interrupt --
  1354.  *
  1355.  *      Call the proper interrupt handler for the given interrupt.
  1356.  *
  1357.  * Results:
  1358.  *      MACH_KERN_ERROR if the machine should go into the debugger, or MACH_OK
  1359.  *    otherwise.
  1360.  *
  1361.  * Side effects:
  1362.  *      None.
  1363.  *
  1364.  * ----------------------------------------------------------------------------
  1365.  */
  1366. static ReturnStatus
  1367. Interrupt(statusReg, causeReg, pc)
  1368.     unsigned    statusReg;
  1369.     unsigned    causeReg;
  1370.     Address    pc;
  1371. {
  1372.     int        n;
  1373.     unsigned    mask;
  1374.     ReturnStatus status = MACH_OK;
  1375.  
  1376.     mask = (causeReg & statusReg & MACH_CR_INT_PENDING) >> 
  1377.                         MACH_CR_HARD_INT_SHIFT;
  1378.     mach_KernelMode = !(statusReg & MACH_SR_KU_PREV);
  1379.     mach_AtInterruptLevel = 1;
  1380.  
  1381.     /*
  1382.      * If there is a memory interrupt pending, and we have all other
  1383.      * interrupts off, then only handle that interrupt.
  1384.      */
  1385.  
  1386.     if (mach_NumDisableIntrsPtr[Mach_GetProcessorNumber()] > 0) {
  1387.     if (mask & (MACH_INT_MASK_3 >> MACH_CR_HARD_INT_SHIFT)) {
  1388.         status = machInterruptRoutines[3](statusReg, causeReg, pc, 
  1389.             machInterruptArgs[3]); 
  1390.         goto exit;
  1391.     } else {
  1392.         panic("Interrupt while at interrupt level, (0x%x) pc 0x%x.\n", 
  1393.         mask, pc);
  1394.     }
  1395.     }
  1396.     n = 0;
  1397.     while (mask != 0) {
  1398.     if (mask & 1) {
  1399.         (void) machInterruptRoutines[n](statusReg, causeReg, pc, 
  1400.         machInterruptArgs[n]); 
  1401.     }
  1402.     mask >>= 1;
  1403.     n++;
  1404.     }
  1405. exit:
  1406.     mach_AtInterruptLevel = 0;
  1407.     return(status);
  1408. }
  1409.  
  1410.  
  1411. /*
  1412.  * ----------------------------------------------------------------------------
  1413.  *
  1414.  * MachUserReturn --
  1415.  *
  1416.  *      Take the proper action to return from a user exception.
  1417.  *
  1418.  * Results:
  1419.  *      None.
  1420.  *
  1421.  * Side effects:
  1422.  *      Interrupts disabled.
  1423.  *
  1424.  * ----------------------------------------------------------------------------
  1425.  */
  1426. Boolean
  1427. MachUserReturn(procPtr)
  1428.     register    Proc_ControlBlock    *procPtr;
  1429. {
  1430.     SignalStack    sigStack;
  1431.     Address    pc;
  1432.     int        restarted = 0;
  1433.  
  1434.  
  1435.     if (procPtr->Prof_Scale >= 2 && procPtr->Prof_PC != 0) {
  1436.     Prof_RecordPC(procPtr);
  1437.     }
  1438.  
  1439.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX &&
  1440.         procPtr->unixProgress != PROC_PROGRESS_UNIX && debugProcStubs) {
  1441.     printf("UnixProgress = %d entering MachUserReturn\n",
  1442.         procPtr->unixProgress);
  1443.     }
  1444.  
  1445.     /* 
  1446.      * Take a context switch if one is pending for this process.
  1447.      */
  1448.     if (procPtr->schedFlags & SCHED_CONTEXT_SWITCH_PENDING) {
  1449.     Sched_LockAndSwitch();
  1450.     }
  1451.  
  1452.     while (TRUE) {
  1453.     /*
  1454.      * See if we are supposed to single-step this process.  If so
  1455.      * put a break in the proper place.  Don't worry if we miss a signal
  1456.      * because we will be back in real soon anyway (after one instruction).
  1457.      */
  1458.     if (procPtr->genFlags & PROC_SINGLE_STEP_FLAG) {
  1459.         Address        breakPC;
  1460.         unsigned        breakInst;
  1461.         ReturnStatus    status;
  1462.         int            accLen;
  1463.         Address        newAddr;
  1464.  
  1465.         if (machFPCurStatePtr == machCurStatePtr) {
  1466.         MachGetCurFPState(machCurStatePtr);
  1467.         }
  1468.         Vm_MakeAccessible(VM_READONLY_ACCESS, sizeof(Address),
  1469.                   machCurStatePtr->userState.regState.pc, 
  1470.                   &accLen, &newAddr);
  1471.         if (accLen != sizeof(Address)) {
  1472.         printf("MachUserReturn: Can't fetch user's trap PC\n");
  1473.         break;
  1474.         }
  1475.         breakPC = (Address)
  1476.             MachEmulateBranch(machCurStatePtr->userState.regState.regs,
  1477.                       machCurStatePtr->userState.regState.pc,
  1478.                  machCurStatePtr->userState.regState.fpStatusReg,
  1479.                          TRUE);
  1480.         Vm_MakeUnaccessible(newAddr, sizeof(Address));
  1481.         if (Vm_CopyIn(4, breakPC,
  1482.               (Address)&machCurStatePtr->sstepInst) != SUCCESS) {
  1483.         printf("Bad single-step address\n");
  1484.         } else {
  1485.         breakInst = MACH_SSTEP_VAL | 0xd;
  1486.         Vm_ChangeCodeProt(procPtr, breakPC, 4, TRUE);
  1487.         status = Vm_CopyOut(4, (Address)&breakInst, breakPC);
  1488.         Vm_ChangeCodeProt(procPtr, breakPC, 4, FALSE);
  1489.         Vm_FlushCode(procPtr, breakPC, 4);
  1490.         if (status != SUCCESS) {
  1491.             printf("Bad single-step address\n");
  1492.         }
  1493.         }
  1494.         procPtr->genFlags &= ~PROC_SINGLE_STEP_FLAG;
  1495.         Mach_DisableIntr();
  1496.         break;
  1497.     } else {
  1498.         if (procPtr->unixProgress == PROC_PROGRESS_RESTART ||
  1499.             procPtr->unixProgress > 0) {
  1500.         /*
  1501.          * If we received a normal signal, we want to restart
  1502.          * the system call when we leave.
  1503.          * If we received a migrate signal, we will get here on
  1504.          * the new machine.
  1505.          */
  1506.  
  1507.         /*
  1508.          * Mangle the PC so we restart the trap after we leave
  1509.          * the kernel.
  1510.          */
  1511.         restarted = 1;
  1512.         if (debugProcStubs) {
  1513.             printf("Restarting system call with progress %d\n",
  1514.                 procPtr->unixProgress);
  1515.             printf("Our PC = %x\n",
  1516.                 machCurStatePtr->userState.regState.pc);
  1517.         }
  1518.         machCurStatePtr->userState.regState.pc -= 4;
  1519.         if (debugProcStubs) {
  1520.             printf("Now our PC = %x\n",
  1521.                 machCurStatePtr->userState.regState.pc);
  1522.             printf("V0 was %d and our call was %d\n", 
  1523.                 machCurStatePtr->userState.regState.regs[V0],
  1524.                 machCurStatePtr->userState.unixRetVal);
  1525.         }
  1526.         machCurStatePtr->userState.regState.regs[V0] =
  1527.             machCurStatePtr->userState.unixRetVal;
  1528.         procPtr->unixProgress = PROC_PROGRESS_UNIX;
  1529.         }
  1530.         /*
  1531.          * Disable interrupts.  Note that we don't use the DISABLE_INTR 
  1532.          * macro because it increments the nesting depth of interrupts
  1533.          * which we don't want because there is an implicit enable
  1534.          * interrupts on rte.
  1535.          */
  1536.         Mach_DisableIntr();
  1537.         if (!Sig_Pending(procPtr)) {
  1538.         break;
  1539.         }
  1540.         Mach_EnableIntr();
  1541.         sigStack.sigStack.contextPtr = &sigStack.sigContext;
  1542.         if (Sig_Handle(procPtr, &sigStack.sigStack, &pc)) {
  1543.         SetupSigHandler(procPtr, &sigStack, pc);
  1544.         Mach_DisableIntr();
  1545.         break;
  1546.         } else if (restarted && debugProcStubs) {
  1547.         printf("No signal, yet we restarted system call!!?!\n");
  1548.         }
  1549.     }
  1550.     }
  1551.     
  1552.     /*
  1553.      * It is possible for Sig_Handle to mask the migration signal
  1554.      * if a process is not in a state where it can be migrated.
  1555.      * As soon as we return to user mode, though, we will allow migration.
  1556.      */
  1557.     Sig_AllowMigration(procPtr);
  1558.  
  1559.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX &&
  1560.         procPtr->unixProgress != PROC_PROGRESS_UNIX && debugProcStubs) {
  1561.     printf("UnixProgress = %d leaving MachUserReturn\n", procPtr->unixProgress);
  1562.     }
  1563.  
  1564.     return(machFPCurStatePtr == machCurStatePtr);
  1565. }
  1566.  
  1567.  
  1568. /*
  1569.  * ----------------------------------------------------------------------------
  1570.  *
  1571.  * Routines to set up and return from signal handlers.
  1572.  *
  1573.  * In order to call a handler four things must be done:
  1574.  *
  1575.  *    1) The current state of the process must be saved so that when
  1576.  *       the handler returns a normal return to user space can occur.
  1577.  *    2) The user stack must be set up so that the signal number and the
  1578.  *       the signal code are passed to the handler.
  1579.  *    3) Things must be set up so that when the handler returns it returns
  1580.  *       back into the kernel so that state can be cleaned up.
  1581.  *    4) The trap stack that was created when the kernel was entered and is
  1582.  *       used to return a process to user space must be modified so that
  1583.  *       the signal handler is called instead of executing the
  1584.  *       normal return.
  1585.  *
  1586.  * The last one is done by simply changing the program counter where the
  1587.  * user process will execute on return to be the address of the signal
  1588.  * handler and the user stack pointer to point to the proper place on
  1589.  * the user stack.  The first three of these are accomplished by 
  1590.  * setting up the user's registers properly.  The return address register is the
  1591.  * return address where the handler will start executing upon return.  But 
  1592.  * this is just the address of a trap instruction that is stored on the stack
  1593.  * below.  Thus when a handler returns it will execute a trap instruction 
  1594.  * and drop back into the kernel. 
  1595.  */
  1596.  
  1597.  
  1598. /*
  1599.  * ----------------------------------------------------------------------------
  1600.  *
  1601.  * SetupSigHandler --
  1602.  *
  1603.  *      Save machine state on the users stack and set up the exception stack
  1604.  *    so that the user will call the signal handler on return. In order to
  1605.  * Results:
  1606.  *      None.
  1607.  *
  1608.  * Side effects:
  1609.  *      Signal stack set up and saved.
  1610.  *
  1611.  * ----------------------------------------------------------------------------
  1612.  */
  1613. static void
  1614. SetupSigHandler(procPtr, sigStackPtr, pc)
  1615.     register    Proc_ControlBlock    *procPtr;
  1616.     register    SignalStack        *sigStackPtr;
  1617.     Address                pc;
  1618. {
  1619.     Mach_UserState    *userStatePtr;
  1620.     unsigned        usp;
  1621.  
  1622.     userStatePtr = &procPtr->machStatePtr->userState;
  1623.     usp = userStatePtr->regState.regs[SP] - sizeof(Sig_Context) - 
  1624.       MACH_STAND_FRAME_SIZE;
  1625.  
  1626.     sigStackPtr->sigContext.machContext.break1Inst = 0x1000d;
  1627.     /*
  1628.      * Copy the user state onto the signal stack.
  1629.      */
  1630.     bcopy((Address)userStatePtr,
  1631.           (Address)&(sigStackPtr->sigContext.machContext.userState),
  1632.           sizeof(Mach_UserState));
  1633.     /*
  1634.      * Copy over the floating point state.
  1635.      */
  1636.     if (machFPCurStatePtr == machCurStatePtr) {
  1637.     MachGetCurFPState(machCurStatePtr);
  1638.     }
  1639.     bcopy((Address)procPtr->machStatePtr->userState.regState.fpRegs,
  1640.       (Address)sigStackPtr->sigContext.machContext.fpRegs,
  1641.       MACH_NUM_FPRS * sizeof(int));
  1642.     sigStackPtr->sigContext.machContext.fpStatusReg =
  1643.             procPtr->machStatePtr->userState.regState.fpStatusReg;
  1644.     /*
  1645.      * Copy the stack out to user space.
  1646.      */
  1647.     if (Vm_CopyOut(sizeof(Sig_Context), (Address)&sigStackPtr->sigContext,
  1648.             (Address)(usp + MACH_STAND_FRAME_SIZE)) != SUCCESS) {
  1649.         printf("Warning: HandleSig: No room on stack for signal, PID=%x.\n",
  1650.                   procPtr->processID);
  1651.         Proc_ExitInt(PROC_TERM_DESTROYED, PROC_BAD_STACK, 0);
  1652.     }
  1653.     /*
  1654.      * Now set up the registers correctly.
  1655.      */
  1656.     userStatePtr->regState.regs[SP] = usp;
  1657.     if (procPtr->unixProgress != PROC_PROGRESS_NOT_UNIX) {
  1658.     int unixSignal;
  1659.     if (Compat_SpriteSignalToUnix(sigStackPtr->sigStack.sigNum,
  1660.         &unixSignal) != SUCCESS) {
  1661.         printf("Signal %d invalid in SetupSigHandler\n",
  1662.             sigStackPtr->sigStack.sigNum);
  1663.     } else {
  1664.         userStatePtr->regState.regs[A0] = unixSignal;
  1665.     }
  1666.     } else {
  1667.     userStatePtr->regState.regs[A0] = sigStackPtr->sigStack.sigNum;
  1668.     }
  1669.     userStatePtr->regState.regs[A1] = sigStackPtr->sigStack.sigCode;
  1670.     userStatePtr->regState.regs[A2] = usp + MACH_STAND_FRAME_SIZE;
  1671.     userStatePtr->regState.regs[A3] = sigStackPtr->sigStack.sigAddr;
  1672.     userStatePtr->regState.pc = pc;
  1673.     userStatePtr->regState.regs[RA] = usp + MACH_STAND_FRAME_SIZE + 
  1674.         (unsigned)&((Sig_Context *)0)->machContext.break1Inst;
  1675. }
  1676.  
  1677.  
  1678. /*
  1679.  * ----------------------------------------------------------------------------
  1680.  *
  1681.  * ReturnFromSigHandler --
  1682.  *
  1683.  *      Process a return from a signal handler.
  1684.  *    
  1685.  * Results:
  1686.  *      None.
  1687.  *
  1688.  * Side effects:
  1689.  *      Signal stack struct and size filled in the machine struct for the
  1690.  *    given process.
  1691.  *
  1692.  * ----------------------------------------------------------------------------
  1693.  */
  1694. static void
  1695. ReturnFromSigHandler(procPtr)
  1696.     register    Proc_ControlBlock    *procPtr;
  1697. {
  1698.     register    Mach_State    *statePtr;
  1699.     SignalStack            sigStack;
  1700.  
  1701.     statePtr = procPtr->machStatePtr;
  1702.     /*
  1703.      * Copy the signal stack in.
  1704.      */
  1705.     if (Vm_CopyIn(sizeof(Sig_Context),
  1706.           (Address)(statePtr->userState.regState.regs[SP] + 
  1707.                 MACH_STAND_FRAME_SIZE),
  1708.           (Address) &sigStack.sigContext) != SUCCESS) {
  1709.     printf("%s Mach_Code: Stack too small to extract trap info, PID=%x.\n",
  1710.         "Warning:", procPtr->processID);
  1711.     Proc_ExitInt(PROC_TERM_DESTROYED, PROC_BAD_STACK, 0);
  1712.     }
  1713.     sigStack.sigStack.contextPtr = &sigStack.sigContext;
  1714.     /*
  1715.      * Take the proper action on return from a signal.
  1716.      */
  1717.     Sig_Return(procPtr, &sigStack.sigStack);
  1718.     /*
  1719.      * Restore user state.
  1720.      */
  1721.     bcopy((Address)&sigStack.sigContext.machContext.userState,
  1722.           (Address)&statePtr->userState, sizeof(statePtr->userState));
  1723.     /*
  1724.      * Copy in the floating point state.
  1725.      */
  1726.     bcopy((Address)sigStack.sigContext.machContext.fpRegs,
  1727.       (Address)statePtr->userState.regState.fpRegs,
  1728.       MACH_NUM_FPRS * sizeof(int));
  1729.     statePtr->userState.regState.fpStatusReg = 
  1730.     sigStack.sigContext.machContext.fpStatusReg & ~MACH_FPC_EXCEPTION_BITS;
  1731.     if (machFPCurStatePtr == machCurStatePtr) {
  1732.     machFPCurStatePtr = (Mach_State *)NIL;
  1733.     }
  1734. }
  1735.  
  1736.  
  1737. /*
  1738.  * ----------------------------------------------------------------------------
  1739.  *
  1740.  * Mach_ProcessorState --
  1741.  *
  1742.  *    Determines what state the processor is in.
  1743.  *
  1744.  * Results:
  1745.  *    MACH_USER    if was at user level
  1746.  *    MACH_KERNEL    if was at kernel level
  1747.  *
  1748.  * Side effects:
  1749.  *    None.
  1750.  *
  1751.  * ----------------------------------------------------------------------------
  1752.  */
  1753. /*ARGSUSED*/
  1754. Mach_ProcessorStates 
  1755. Mach_ProcessorState(processor)
  1756.     int processor;    /* processor number for which info is requested */
  1757. {
  1758.     if (mach_KernelMode) {
  1759.     return(MACH_KERNEL);
  1760.     } else {
  1761.     return(MACH_USER);
  1762.     }
  1763. }
  1764.  
  1765.  
  1766. /*
  1767.  * ----------------------------------------------------------------------------
  1768.  *
  1769.  * Mach_GetMachineArch --
  1770.  *
  1771.  *    Return the machine architecture.
  1772.  *
  1773.  * Results:
  1774.  *    The machine architecture.
  1775.  *
  1776.  * Side effects:
  1777.  *    None.
  1778.  *
  1779.  * ----------------------------------------------------------------------------
  1780.  */
  1781. int
  1782. Mach_GetMachineArch()
  1783. {
  1784.     return SYS_DS5000;
  1785. }
  1786.  
  1787.  
  1788. /*
  1789.  * ----------------------------------------------------------------------------
  1790.  *
  1791.  * Mach_GetMachineType --
  1792.  *
  1793.  *    Return the machine type.
  1794.  *
  1795.  * Results:
  1796.  *    0.
  1797.  *
  1798.  * Side effects:
  1799.  *    None.
  1800.  *
  1801.  * ----------------------------------------------------------------------------
  1802.  */
  1803. int
  1804. Mach_GetMachineType()
  1805. {
  1806.     return 0;
  1807. }
  1808.  
  1809.  
  1810. /*
  1811.  * ----------------------------------------------------------------------------
  1812.  *
  1813.  *  Mach_CheckSpecialHandling--
  1814.  *
  1815.  *    Forces a processor to check the special handling flag of a process.
  1816.  *    This should only be called on a multiprocessor.
  1817.  *
  1818.  * Results:
  1819.  *    None.
  1820.  *
  1821.  * Side effects:
  1822.  *    None.
  1823.  *
  1824.  * ----------------------------------------------------------------------------
  1825.  */
  1826. void
  1827. Mach_CheckSpecialHandling(pnum)
  1828.     int        pnum;        /* Processor number. */
  1829. {
  1830.     panic("Mach_CheckSpecialHandling called for processor %d\n",pnum);
  1831. }
  1832.  
  1833.  
  1834. /*
  1835.  *----------------------------------------------------------------------
  1836.  *
  1837.  * Mach_GetNumProcessors() --
  1838.  *
  1839.  *    Return the number of processors in the system.  NOTE: This should
  1840.  *    really be in a machine-independent area of the mach module.  Note
  1841.  *    further: if this is used only as a system call, it should return
  1842.  *    a ReturnStatus!
  1843.  *
  1844.  * Results:
  1845.  *    The number of processors is returned.  
  1846.  *
  1847.  * Side effects:
  1848.  *    None
  1849.  *
  1850.  *----------------------------------------------------------------------
  1851.  */
  1852.  
  1853. int
  1854. Mach_GetNumProcessors()
  1855. {
  1856.     return (mach_NumProcessors);
  1857. }
  1858.  
  1859.  
  1860. /*
  1861.  *----------------------------------------------------------------------
  1862.  *
  1863.  * Mach_GetBootArgs --
  1864.  *
  1865.  *    Returns the arguments out of the boot parameter structure. 
  1866.  *
  1867.  * Results:
  1868.  *    Number of elements returned in argv.
  1869.  *
  1870.  * Side effects:
  1871.  *    None.
  1872.  *
  1873.  *----------------------------------------------------------------------
  1874.  */
  1875. /*ARGSUSED*/
  1876. int
  1877. Mach_GetBootArgs(argc, bufferSize, argv, buffer)
  1878.     int    argc;            /* Number of elements in argv */
  1879.     int    bufferSize;        /* Size of buffer */
  1880.     char    **argv;            /* Ptr to array of arg pointers */
  1881.     char    *buffer;        /* Storage for arguments */
  1882. {
  1883.     int        i;
  1884.     int        offset;
  1885.  
  1886.     bcopy(machMonBootParam.strings, buffer, 
  1887.       (bufferSize < 256) ? bufferSize : 256);
  1888.     offset = (int) machMonBootParam.strings - (int) buffer;
  1889.     for(i = 0; i < argc; i++) {
  1890.     if (machMonBootParam.argPtr[i] == (char *)NULL) {
  1891.         break;
  1892.     }
  1893.     argv[i] = (char *) (machMonBootParam.argPtr[i] - (char *) offset);
  1894.     }
  1895.     return i;
  1896. }
  1897.  
  1898. /*
  1899.  *----------------------------------------------------------------------
  1900.  *
  1901.  * MachMemInterrupt --
  1902.  *
  1903.  *    Handle an interrupt from the memory controller.
  1904.  *
  1905.  * Results:
  1906.  *    None.
  1907.  *
  1908.  * Side effects:
  1909.  *    None.
  1910.  *
  1911.  *----------------------------------------------------------------------
  1912.  */
  1913. /*ARGSUSED*/
  1914. static ReturnStatus
  1915. MachMemInterrupt(statusReg, causeReg, pc, data)
  1916.     unsigned    statusReg;        /* Status register. */
  1917.     unsigned    causeReg;        /* Cause register. */
  1918.     Address    pc;            /* PC. */
  1919.     ClientData    data;            /* Callback data. */
  1920.  
  1921. {
  1922.     volatile unsigned int *erradrPtr = 
  1923.         (volatile unsigned int *) MACH_ERRADR_ADDR;
  1924.     unsigned int erradr;
  1925.     volatile unsigned int *chksynPtr = 
  1926.         (volatile unsigned int *) MACH_CHKSYN_ADDR;
  1927.     unsigned int chksyn;
  1928.     unsigned int address;
  1929.     int        column;
  1930.     ReturnStatus    status = MACH_OK;
  1931.  
  1932.     erradr = *erradrPtr;
  1933.     if (!(erradr & MACH_ERRADR_VALID)) {
  1934.     printf("Received memory interrupt but ERRADR not valid.\n");
  1935.     return status;
  1936.     }
  1937.     address = erradr & MACH_ERRADR_ADDRESS;
  1938.     switch((int) (erradr & 
  1939.     (MACH_ERRADR_CPU | MACH_ERRADR_WRITE | MACH_ERRADR_ECCERR))){
  1940.     case 0: {
  1941.         /*
  1942.          * For IO space addresses the 27 bits in the ERRADR must be
  1943.          * shifted by 2, then the top bits set.  This isn't documented
  1944.          * anywhere.
  1945.          */
  1946.         address = MACH_IO_SLOT_BASE | (address << 2);
  1947.         panic("DMA read overrun at address 0x%x\n", address);
  1948.         break;
  1949.     } 
  1950.     case (MACH_ERRADR_ECCERR) :  {
  1951.         /*
  1952.          * Compensate for the address pipeline. 
  1953.          * See page 26 of the functional spec.
  1954.          */
  1955.         column = (int) (address & 0xfff); 
  1956.         column -= 5;
  1957.         address = (address & ~0xfff) | (unsigned int) column;
  1958.         printf("ECC read error during DMA at address 0x%x\n", address);
  1959.         break;
  1960.     }
  1961.     case (MACH_ERRADR_WRITE) : {
  1962.         address = MACH_IO_SLOT_BASE | (address << 2);
  1963.         panic("DMA write overrun at address 0x%x, pc = 0x%x\n", 
  1964.         address, pc);
  1965.         break;
  1966.     } 
  1967.     case (MACH_ERRADR_WRITE | MACH_ERRADR_ECCERR) : {
  1968.         printf("Holy bogus hardware, Batman!\n");
  1969.         printf("We got an illegal value in the ERRADR status register.\n");
  1970.         break;
  1971.     }
  1972.     case (MACH_ERRADR_CPU) : {
  1973.         address = MACH_IO_SLOT_BASE | (address << 2);
  1974.         if (machInProbe) {
  1975.         status = MACH_USER_ERROR;
  1976.         machInProbe = FALSE;
  1977.         break;
  1978.         }
  1979.         panic(
  1980.     "Timeout during CPU read of IO address 0x%x, pc = 0x%x\n", 
  1981.     address, pc);
  1982.         Mach_SendSignal(MACH_SIGILL);
  1983.         break;
  1984.     }
  1985.     case (MACH_ERRADR_CPU | MACH_ERRADR_ECCERR) : {
  1986.         /*
  1987.          * Compensate for the address pipeline. 
  1988.          * See page 26 of the functional spec.
  1989.          */
  1990.         column = (int) (address & 0xfff); 
  1991.         column -= 5;
  1992.         address = (address & ~0xfff) | (unsigned int) column;
  1993.         printf("ECC read error during CPU access of address 0x%x\n", 
  1994.         address);
  1995.         break;
  1996.     }
  1997.     case (MACH_ERRADR_CPU | MACH_ERRADR_WRITE) : {
  1998.         address = MACH_IO_SLOT_BASE | (address << 2);
  1999.         if (machInProbe) {
  2000.         status = MACH_USER_ERROR;
  2001.         machInProbe = FALSE;
  2002.         break;
  2003.         }
  2004.         panic(
  2005.     "Timeout during CPU write of IO address 0x%x\n, pc = 0x%x\n", 
  2006.     address, pc);
  2007.         break;
  2008.     }
  2009.     case (MACH_ERRADR_CPU | MACH_ERRADR_WRITE | MACH_ERRADR_ECCERR) : {
  2010.         printf("ECC partial memory write error by CPU at address 0x%x\n",
  2011.         address);
  2012.         break;
  2013.     }
  2014.     }
  2015.     if (erradr & MACH_ERRADR_ECCERR) {
  2016.     chksyn = *chksynPtr;
  2017.     if (address & 0x1) {
  2018.         printf("ECC error was in the high bank.\n");
  2019.         printf("%s bit error\n", (chksyn & MACH_CHKSYN_SNGHI) ? 
  2020.         "single" : "multiple");
  2021.         printf("Syndrome bits = 0x%x\n", chksyn & MACH_CHKSYN_SYNHI);
  2022.         if (chksyn & MACH_CHKSYN_VLDHI) {
  2023.         printf("Check bits = 0x%x\n", chksyn & MACH_CHKSYN_CHKHI);
  2024.         } else {
  2025.         printf("Check bits not valid.\n");
  2026.         }
  2027.     } else {
  2028.         printf("ECC error was in the low bank.\n");
  2029.         printf("%s bit error\n", (chksyn & MACH_CHKSYN_SNGLO) ? 
  2030.         "single" : "multiple");
  2031.         printf("Syndrome bits = 0x%x\n", chksyn & MACH_CHKSYN_SYNLO);
  2032.         if (chksyn & MACH_CHKSYN_VLDLO) {
  2033.         printf("Check bits = 0x%x\n", chksyn & MACH_CHKSYN_CHKLO);
  2034.         } else {
  2035.         printf("Check bits not valid.\n");
  2036.         }
  2037.     }
  2038.     }
  2039.     /*
  2040.      * Clear the ERRADR and CHKSYN registers.
  2041.      */
  2042.     *erradrPtr = 0;
  2043.     return status;
  2044. }
  2045.  
  2046. /*
  2047.  *----------------------------------------------------------------------
  2048.  *
  2049.  * MachIOInterrupt --
  2050.  *
  2051.  *    Handle an interrupt from one of the IO slots.
  2052.  *
  2053.  * Results:
  2054.  *    None.
  2055.  *
  2056.  * Side effects:
  2057.  *    None.
  2058.  *
  2059.  *----------------------------------------------------------------------
  2060.  */
  2061. /*ARGSUSED*/
  2062. static ReturnStatus
  2063. MachIOInterrupt(statusReg, causeReg, pc, data)
  2064.     unsigned int    statusReg;    /* Status register. */
  2065.     unsigned int    causeReg;    /* Cause register. */
  2066.     Address        pc;        /* PC. */
  2067.     ClientData        data;        /* Not used. */
  2068. {
  2069.     volatile unsigned int     *csrPtr = (unsigned int *) MACH_CSR_ADDR;
  2070.     unsigned int         csr;
  2071.     int                slot;
  2072.     unsigned int        ioint;
  2073.  
  2074.     csr = *csrPtr;
  2075.     ioint = csr & MACH_CSR_IOINT;
  2076.     if (ioint == 0) {
  2077.     panic("No interrupt pending on an IO slot.\n");
  2078.     }
  2079.     for (slot = 0; ioint != 0; slot++, ioint >>= 1) {
  2080.     if (ioint & 1) {
  2081.         if (machIOInterruptRoutines[slot] != (void (*)()) NIL) {
  2082.         machIOInterruptRoutines[slot](machIOInterruptArgs[slot]);
  2083.         }
  2084.     }
  2085.     }
  2086.     return MACH_OK;
  2087. }
  2088.  
  2089.  
  2090. /*
  2091.  *----------------------------------------------------------------------
  2092.  *
  2093.  * Mach_FlushCode --
  2094.  *
  2095.  *    Flush the kernel code from the icache at the given address.
  2096.  *
  2097.  * Results:
  2098.  *    None.
  2099.  *
  2100.  * Side effects:
  2101.  *    None.
  2102.  *
  2103.  *----------------------------------------------------------------------
  2104.  */
  2105. void
  2106. Mach_FlushCode(addr, len) 
  2107.     Address    addr;
  2108.     unsigned    len;
  2109. {
  2110.     unsigned cacheAddr;
  2111.  
  2112.     cacheAddr = VMMACH_PHYS_UNCACHED_START - machInstCacheSize +  
  2113.         ((unsigned)addr & (machInstCacheSize - 1));
  2114. #ifdef notdef
  2115.     printf("len=%d addr=%x cacheAddr=%x\n", len, addr, cacheAddr);
  2116. #endif
  2117.     MachCleanICache(cacheAddr, len);
  2118. }
  2119.  
  2120.  
  2121. /*
  2122.  *----------------------------------------------------------------------
  2123.  *
  2124.  * Mach_SendSignal
  2125.  *
  2126.  *    Send either an illegal instruction or a floating point exception
  2127.  *    to the current process.
  2128.  *
  2129.  * Results:
  2130.  *    None.
  2131.  *
  2132.  * Side effects:
  2133.  *    None.
  2134.  *
  2135.  *----------------------------------------------------------------------
  2136.  */
  2137. void
  2138. Mach_SendSignal(sigType)
  2139.     int    sigType;
  2140. {
  2141.     Proc_ControlBlock    *procPtr;
  2142.  
  2143.     procPtr = Proc_GetActualProc();
  2144.  
  2145.     printf("Mach_SendSignal: Sending signal\n");
  2146.  
  2147.     switch ((int)sigType) {
  2148.     case MACH_SIGFPE:
  2149.         (void) Sig_Send(SIG_ILL_INST, SIG_FP_EXCEPTION,
  2150.                 procPtr->processID, FALSE, (Address)0);
  2151.         break;
  2152.     case MACH_SIGILL:
  2153.         (void) Sig_Send(SIG_ILL_INST, SIG_ILL_INST_CODE,
  2154.                 procPtr->processID, FALSE, (Address)0);
  2155.         break;
  2156.     default:
  2157.         panic("Mach_SendSignal: Bad signal type\n");
  2158.         break;
  2159.     }
  2160. }
  2161.  
  2162.  
  2163. /*
  2164.  *----------------------------------------------------------------------
  2165.  *
  2166.  * Mach_ArgParseCode --
  2167.  *
  2168.  *    Parse an argument string.
  2169.  *      Note: this replaces the DECstation argvize prom call that has
  2170.  *    been disabled on the ds5000 for no good reason.
  2171.  *
  2172.  * Results:
  2173.  *    Returns argc,argv in table.
  2174.  *
  2175.  * Side effects:
  2176.  *    None.
  2177.  *
  2178.  *----------------------------------------------------------------------
  2179.  */
  2180. Mach_ArgParseCode(string,table)
  2181. char *string;
  2182. MachStringTable *table;
  2183. {
  2184.     char *ptr1, *ptr2,*end2;
  2185.     table->num = 0;
  2186.     ptr1 = string;
  2187.     ptr2 = table->strings;
  2188.     end2 = table->strings+256;
  2189.     table->argPtr[0] = ptr2;
  2190.     for (;*ptr1 != 0 && ptr2<end2; ptr2++) {
  2191.     if (*ptr1 == ' ') {
  2192.         while(*ptr1 == ' ') {
  2193.         ptr1++;
  2194.         }
  2195.         if (*ptr1 == '\0') {
  2196.         break;
  2197.         }
  2198.         *ptr2 = '\0';
  2199.         table->num++;
  2200.         if (table->num>=16) {
  2201.         break;
  2202.         }
  2203.         table->argPtr[table->num] = ptr2+1;
  2204.     } else {
  2205.         *ptr2 = *ptr1;
  2206.         ptr1++;
  2207.     }
  2208.     }
  2209. }
  2210.  
  2211. /*
  2212.  *----------------------------------------------------------------------
  2213.  *
  2214.  * Mach_GetEtherAddress --
  2215.  *
  2216.  *    Returns the ethernet address of the first ethernet interface.
  2217.  *
  2218.  * Results:
  2219.  *    None.
  2220.  *
  2221.  * Side effects:
  2222.  *    *etherAddrPtr gets the ethernet address.
  2223.  *
  2224.  *----------------------------------------------------------------------
  2225.  */
  2226.  
  2227. void
  2228. Mach_GetEtherAddress(etherAddrPtr)
  2229.     Net_EtherAddress    *etherAddrPtr;    /* Place to put ethernet address. */
  2230. {
  2231.     Net_Interface    *interPtr;
  2232.  
  2233.     interPtr = Net_GetInterface(NET_NETWORK_ETHER, 0);
  2234.     if (interPtr != (Net_Interface *) NIL) {
  2235.     NET_ETHER_ADDR_COPY(interPtr->netAddress[NET_PROTO_RAW].ether,
  2236.         *etherAddrPtr);
  2237.     }
  2238. }
  2239.  
  2240. #define READ_ROM(from, to, count) {             \
  2241.     int    _i;                        \
  2242.     for(_i = 0; _i < (count); _i++) {            \
  2243.     status = Mach_Probe(1, (from), &((to)[_i]));    \
  2244.     if (status != SUCCESS) {            \
  2245.         return status;                \
  2246.     }                        \
  2247.     (from) += 4;                    \
  2248.     }                            \
  2249. }
  2250.  
  2251. /*
  2252.  *----------------------------------------------------------------------
  2253.  *
  2254.  * Mach_GetSlotInfo --
  2255.  *
  2256.  *    Read the standard information from the ROM in a TURBOchannel
  2257.  *     slot.  Any trailing spaces are converted to null characters.
  2258.  *    See page 13 of the TURBOchannel Hardware Specification for
  2259.  *     details on the format of the ROM.
  2260.  *
  2261.  * Results:
  2262.  *    SUCCESS if the ROM was read ok, FAILURE otherwise
  2263.  *
  2264.  * Side effects:
  2265.  *    None.
  2266.  *
  2267.  *----------------------------------------------------------------------
  2268.  */
  2269. ReturnStatus
  2270. Mach_GetSlotInfo(romAddr, infoPtr)
  2271.     char        *romAddr;    /* ROM address. */
  2272.     Mach_SlotInfo    *infoPtr;    /* Slot information. */
  2273. {
  2274.     ReturnStatus    status = SUCCESS;
  2275.     unsigned char    value;
  2276.     int            i;
  2277.  
  2278.  
  2279.     /*
  2280.      * Move to the start of the standard TURBOchannel rom info. 
  2281.      */
  2282.     romAddr += MACH_IO_ROM_OFFSET + 0x10;
  2283.     /*
  2284.      * Check the test pattern.
  2285.      */
  2286.     READ_ROM(romAddr, &value, 1);
  2287.     if (value != 0x55) {
  2288.     return FAILURE;
  2289.     }
  2290.     READ_ROM(romAddr, &value, 1);
  2291.     if (value != 0x00) {
  2292.     return FAILURE;
  2293.     }
  2294.     READ_ROM(romAddr, &value, 1);
  2295.     if (value != 0xaa) {
  2296.     return FAILURE;
  2297.     }
  2298.     READ_ROM(romAddr, &value, 1);
  2299.     if (value != 0xff) {
  2300.     return FAILURE;
  2301.     }
  2302.     /*
  2303.      * Everything looks cool so read out the info.
  2304.      */
  2305.     READ_ROM(romAddr, infoPtr->revision, 8);
  2306.     READ_ROM(romAddr, infoPtr->vendor, 8);
  2307.     READ_ROM(romAddr, infoPtr->module, 8);
  2308.     READ_ROM(romAddr, infoPtr->type, 4);
  2309.     /*
  2310.      * Get rid of trailing spaces
  2311.      */
  2312.     for (i = 7; i >= 0; i--) {
  2313.     if (infoPtr->revision[i] == ' ') {
  2314.         infoPtr->revision[i] = '\0';
  2315.     }
  2316.     if (infoPtr->revision[i] != '\0') {
  2317.         break;
  2318.     } 
  2319.     }
  2320.     for (i = 7; i >= 0; i--) {
  2321.     if (infoPtr->vendor[i] == ' ') {
  2322.         infoPtr->vendor[i] = '\0';
  2323.     }
  2324.     if (infoPtr->vendor[i] != '\0') {
  2325.         break;
  2326.     } 
  2327.     }
  2328.     for (i = 7; i >= 0; i--) {
  2329.     if (infoPtr->module[i] == ' ') {
  2330.         infoPtr->module[i] = '\0';
  2331.     }
  2332.     if (infoPtr->module[i] != '\0') {
  2333.         break;
  2334.     } 
  2335.     }
  2336.     for (i = 3; i >= 0; i--) {
  2337.     if (infoPtr->type[i] == ' ') {
  2338.         infoPtr->type[i] = '\0';
  2339.     }
  2340.     if (infoPtr->type[i] != '\0') {
  2341.         break;
  2342.     } 
  2343.     }
  2344.     /*
  2345.      * Make sure all the strings are null terminated.
  2346.      */
  2347.     infoPtr->revision[8] = '\0';
  2348.     infoPtr->vendor[8] = '\0';
  2349.     infoPtr->module[8] = '\0';
  2350.     infoPtr->type[4] = '\0';
  2351.     return status;
  2352. }
  2353.  
  2354. /*
  2355.  *----------------------------------------------------------------------
  2356.  *
  2357.  * Mach_SigreturnStub --
  2358.  *
  2359.  *    Procedure to map from Unix sigreturn system call to Sprite.
  2360.  *    On the decstation, this is used for returning from a signal.
  2361.  *    Note: This routine is exactly the same as MachUNIXLongJumpReturn.
  2362.  *    Presumably the other routine will go away as soon as Unix
  2363.  *    compatibility is working.
  2364.  *
  2365.  * Results:
  2366.  *    Error code is returned upon error.  Otherwise SUCCESS is returned.
  2367.  *
  2368.  * Side effects:
  2369.  *    Side effects associated with the system call.
  2370.  *
  2371.  *----------------------------------------------------------------------
  2372.  */
  2373. int
  2374. Mach_SigreturnStub(sigContextPtr)
  2375.     struct sigcontext *sigContextPtr;
  2376. {
  2377.     struct sigcontext    sigContext;
  2378.     Mach_RegState    *regsPtr;
  2379.     ReturnStatus    status;
  2380.     extern Mach_State   *machCurStatePtr;
  2381.  
  2382.     status = Vm_CopyIn(sizeof(struct sigcontext), (Address)sigContextPtr,
  2383.                (Address)&sigContext);
  2384.     if (status != SUCCESS) {
  2385.     return(status);
  2386.     }
  2387.     regsPtr = &machCurStatePtr->userState.regState;
  2388.     regsPtr->pc = (Address)(sigContext.sc_pc - 4);
  2389.     bcopy(sigContext.sc_regs, regsPtr->regs, sizeof(sigContext.sc_regs));
  2390.     regsPtr->mflo = sigContext.sc_mdlo;
  2391.     regsPtr->mfhi = sigContext.sc_mdhi;
  2392.     bcopy(sigContext.sc_fpregs, regsPtr->fpRegs, sizeof(sigContext.sc_fpregs));
  2393.     regsPtr->fpStatusReg = sigContext.sc_fpc_csr;
  2394.     Proc_GetCurrentProc()->sigHoldMask = sigContext.sc_mask;
  2395.     return(SUCCESS);
  2396. }
  2397.